#ifndef _ENGINEMAIN_H
#define _ENGINEMAIN_H

class CTimeDevice; 
class CD3D9Device; 
class CDInput9Device; 
class CDSound9Device; 
class CPhysics; 
class CBSP; 
class CCamera; 
class CObject; 
class CLevel;

#include <stdio.h>
#include <windows.h>
#include "..\common\arraylist.hpp"
#include "..\common\string.h"
#include "..\common\def.h"
#include "..\common\types.h"
#include "..\math\matrix.h"
#include "..\sound\dsound.h"

class EE_EXPORT CEngine
{
public:
	enum EnginePriority { REALTIME = 0, MINIMIZED}; 

private:

	EnginePriority m_ProcessState; 

	class EE_EXPORT CWindow 
	{
	private:
		HINSTANCE	mh_Instance; 
		HWND		mh_Wnd; 
		const char*	mp_Classname; 

	public:
		CWindow(); 

		void	CenterCursor(); 
		HRESULT	SetDimensions(unsigned int width, unsigned int height); 
		HINSTANCE GethInstance(void) { return mh_Instance;  }
		HWND	GetHWnd(void) { return mh_Wnd;  }
		HRESULT	Create(HINSTANCE hInstance,const string szTitle = CEngine::GetLabel()); 
		HRESULT	Release(void); 

		friend class CEngine; 
	}; 

	float			mf_TimeDuration; 
	bool			mb_IsRunning; 
	CTimeDevice*	mp_Time; 
	CD3D9Device*	mp_Render; 
	CDInput9Device*	mp_Input; 
	EESound::CDSound9Device*	mp_Sound; 
	CPhysics*		mp_Physics; 
	CCamera*		mp_Camera; 
	CWindow			m_Window; 
	string			m_ContentDir;
	ArrayList<CObject *> m_Objects; 

	HRESULT (*mp_AppSetStateHook) (void); 
	HRESULT (*mp_AppThinkHook) (float); 
	HRESULT (*mp_AppShutdownHook) (void); 

	HRESULT	ReleaseObjects(); 
	void	LogHostSystem(); 
	
public:

	static string	GetLabel(); 
	static CEngine	*gp_Engine; 
	static CEngine	*GetInstance(void); 
	static void		DeleteInstance(void); 

#ifdef _DEBUG
	static void PrintVector(Vector3f& v, const string& label = "");
#endif

	CEngine(void); 
	~CEngine(void); 

	HRESULT	Release(void); 
	void	SetState(bool bIsRunning, const EnginePriority processPriority = CEngine::REALTIME); 

	void	RegisterObject(CObject *pObject); 
	void	UnregisterObject(CObject *pObject); 
	HRESULT CreateObject(const string &filename,CObject** pOut); 
	HRESULT CreateObject(CObject* pIn); 
	HRESULT CreateLevel(const string &filename, HRESULT (*pObjectLoadHandler)(CBSP*, string&, Matrix4f&), CBSP** pOut);
	void	SetContentDirectory(const string& dirName);
	void	SetAppInitializeFunc(HRESULT (*pFunc) (void)); 
	void	SetAppShutdownFunc(HRESULT (*pFunc) (void)); 
	void	SetAppThinkFunc(HRESULT (*pFunc) (float)); 
	void	StartEngineLoop(void); 

	FILE*	FindFile(const string &sz_filename); 
	const string FindFilepath(const string &sz_filename); 

	float GetTimeDuration() const; 
	ArrayList<CObject*>* GetObjects(void) {return &m_Objects; }
	CEngine::CWindow*	GetWindow(void); 
	CTimeDevice*		GetTime(); 
	CD3D9Device*		GetRenderer(); 
	CDInput9Device*		GetInput(); 
	EESound::CDSound9Device*		GetSound(); 
	CPhysics*			GetPhysics(); 
	CCamera*			GetCamera(); 
}; 


#endif
